package com.zmn.oms.third.tmall.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.product.dubbo.interfaces.channel.product.third.ChannelProductThirdListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalDict;
import com.zmn.manager.lts.interfaces.task.TaskManager;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.baidumap.BaiduMapBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderDutyConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.RedisKeyConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.HttpUtil;
import com.zmn.oms.model.bo.order.OrderBO;
import com.zmn.oms.model.dto.baidumap.LngLatLocation;
import com.zmn.oms.model.dto.order.proxy.CancelOrderDTO;
import com.zmn.oms.model.dto.order.proxy.CreateOrderDTO;
import com.zmn.oms.model.dto.order.proxy.OrderLogDTO;
import com.zmn.oms.model.dto.order.proxy.UpdateOrderDTO;
import com.zmn.oms.model.dto.product.OrderProductDTO;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.model.vo.work.ZsOrderWorkVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.base.util.MasterPhoneUtil;
import com.zmn.oms.third.tmall.TmallConsts;
import com.zmn.oms.third.tmall.TmallPrepayMapper;
import com.zmn.oms.third.tmall.api.TmallProductPrepey;
import com.zmn.oms.third.tmall.dto.*;
import com.zmn.oms.third.tmall.service.TmallService;
import com.zmn.oms.zmn.business.interfaces.proxy.ProxyOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 天猫勤鸽渠道对接实现类
 *
 * @author xiewenbing
 * @date 2021/7/13
 */
@Slf4j
@Service("tmallService")
public class TmallServiceImpl implements TmallService {

    @Autowired
    private ZsOrderWorkQueryBService zsOrderWorkQueryBService;

    @Autowired
    private ProxyOrderBService proxyOrderBService;

    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private OrderExtendService orderExtendService;

    @Autowired
    private WorkFlowContextBService workFlowContextBService;

    @Autowired
    private BaiduMapBService baiduMapBService;

    @Resource
    private TaskManager taskManager;

    @Resource
    private RedisManager redisManager;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private AreaListRemoteService areaListRemoteService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ChannelProductThirdListRemoteService channelProductThirdListRemoteService;


    /**
     * 根据时间段查询工单
     */
    @Override
    public void queryOrderByTime() throws OmsBaseException {

        // 查询redis的缓存订单列表
        if (NumberUtil.isNullOrZero(redisManager.slen(RedisKeyConsts.TMALL_QINGE_ORDER_LIST_REDIS_KEY))) {
            return;
        }

        Set<String> outerIds = redisManager.sgetall(RedisKeyConsts.TMALL_QINGE_ORDER_LIST_REDIS_KEY);
        // 循环读取
        for(String outerId : outerIds) {
            String key = String.format(RedisKeyConsts.TMALL_QINGE_ORDER_STATUS_REDIS_KEY, outerId);
            String value = redisManager.get(key);
            if (StringUtil.isBlank(value)) {
                continue;
            }

            // 解析状态信息
            TmallOrderStatus orderStatus;
            try {
                orderStatus = JSON.parseObject(value,TmallOrderStatus.class);
                if (Objects.isNull(orderStatus)) {
                    continue;
                }

                // 查询订单信息
                this.queryTmallOrderData(orderStatus);
            } catch (Exception e) {
                continue;
            }
        }
    }

    /**
     * 同步派单
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderDistribute(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 查找工单
        Long orderId = orderWorkLogChange.getOrderId();
        Long workId = orderWorkLogChange.getWorkId();

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId,workId);
        if(Objects.isNull(orderWork)) {
            throw new OmsBaseException("查找不到工单信息");
        }

        // 生成同步数据
        String masterName = orderWork.getMasterName();
        TmallJSTOrderDistributeDTO tmallJSTOrderDistributeDTO = new TmallJSTOrderDistributeDTO();

        tmallJSTOrderDistributeDTO.setTmallOrderId(Long.valueOf(orderWork.getOuterId()));
        tmallJSTOrderDistributeDTO.setMasterName(
                Optional.ofNullable(masterName)
                        .filter(name -> name.length() >= 1)
                        .map(name -> String.format("%s工程师", name.substring(0,1)))
                        .orElse(TmallConsts.MASTER_DEFAULT_NAME)
        );
        tmallJSTOrderDistributeDTO.setMasterPhone(
                Optional.ofNullable(orderDetailService.findOrderDetailByKey(orderWork.getOrderId()))
                        .map(orderDetail -> {
                            if (Objects.equals(orderDetail.getBindStatus(), OrderConsts.BIND_STATUS_BIND)
                                    && org.apache.commons.lang3.StringUtils.isNotBlank(orderDetail.getBindTelephone())) {
                                return orderDetail.getBindTelephone();
                            }
                            return null;
                        })
                        .orElse(MasterPhoneUtil.getSafeMasterPhone(orderWork.getCityId()))
        );

        // 发送数据
        log.info("【{}】同步派工消息，【{}】", TmallConsts.CHANNEL_NAME, JSON.toJSONString(tmallJSTOrderDistributeDTO));
        this.postTmallJstRequest(TmallConsts.JSZ_ORDER_DISTRIBUTE_PATH, tmallJSTOrderDistributeDTO);
    }

    /**
     * 同步预约
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderDutytime(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        Date dutyTime = orderWorkLogChange.getDutyTime();

        if (Objects.isNull(dutyTime)) {

            // 判断是否为预约失败
            if (!Objects.equals(orderWorkLogChange.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_FAIL)) {
                return;
            }

            this.syncOrderSuspend(orderWorkLogChange);
            return;
        }

        // 改约
        TmallJSTOrderReserveDTO orderReserveDTO = new TmallJSTOrderReserveDTO();
        orderReserveDTO.setTmallOrderId(Long.valueOf(orderWorkLogChange.getOuterId()));

        // 设置预约时间段
        setTmallReserveTimeSegment(orderReserveDTO, dutyTime);

        // 发送数据
        log.info("【{}】同步工单预约消息，【{}】", TmallConsts.CHANNEL_NAME, JSON.toJSONString(orderReserveDTO));
        this.postTmallJstRequest(TmallConsts.JSZ_ORDER_RESEFVE_PATH, orderReserveDTO);
    }

    /**
     * 同步工单挂起
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderSuspend(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 参数判断
        if (!Objects.equals(orderWorkLogChange.getDutyStatus(),OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            throw new OmsBaseException("工单预约状态不为挂起");
        }

        // 挂起原因转换
        TmallOrderReserveFailReasonEnum reserveFailReasonEnum = TmallOrderReserveFailReasonEnum.getByZmnDutyFailCode(orderWorkLogChange.getReasonCode());

        // 生成请求数据
        TmallJSTOrderSuspendDTO orderSuspendDTO = new TmallJSTOrderSuspendDTO();
        orderSuspendDTO.setTmallOrderId(Long.valueOf(orderWorkLogChange.getOuterId()));
        orderSuspendDTO.setFailCode(reserveFailReasonEnum.getCode());
        orderSuspendDTO.setFailDesc(reserveFailReasonEnum.getDesc());
        orderSuspendDTO.setNextContactTime(orderWorkLogChange.getNextContactTime());

        // 发送数据
        log.info("【{}】同步 工单挂起/预约失败 消息，【{}】", TmallConsts.CHANNEL_NAME, JSON.toJSONString(orderSuspendDTO));
        this.postTmallJstRequest(TmallConsts.JSZ_ORDER_SUSPEND_PATH, orderSuspendDTO);
    }

    /**
     * 同步工单挂起
     * @param orderWorkLogChange
     * @throws OmsBaseException
     */
    @Override
    public void syncOrderSignin(OrderWorkLogChange orderWorkLogChange) throws OmsBaseException {

        // 生成请求数据
        TmallJSTOrderSigninDTO orderSigninDTO = new TmallJSTOrderSigninDTO();
        orderSigninDTO.setTmallOrderId(Long.valueOf(orderWorkLogChange.getOuterId()));

        // 发送数据
        log.info("【{}】同步 工单签到 消息，【{}】", TmallConsts.CHANNEL_NAME, JSON.toJSONString(orderSigninDTO));
        this.postTmallJstRequest(TmallConsts.JSZ_ORDER_SIGNIN_PATH, orderSigninDTO);
    }

    /**
     * 效验核销码
     *
     * @param orderId
     * @param vCode
     */
    @Override
    public void validateVerificationCode(Long orderId, String vCode) throws OmsBaseException {

        if (NumberUtil.isNullOrZero(orderId) || StringUtil.isBlank(vCode)) {
            throw new OmsBaseException("参数不能为空");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId,orderId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("订单不存在");
        }

        if (!Objects.equals(orderWork.getInputType(),OrderConsts.ORDER_INPUT_TYPE_API)) {
            log.info("【{}】订单录入方式不为API接入，不需要核销码验证", TmallConsts.CHANNEL_NAME);
            return;
        }

        if (!Objects.equals(orderWork.getChannelId(),OrderConsts.CHANNEL_ID_TMALL_QINGE_BW)) {
            log.info("【{}】订单来源渠道非天猫勤鸽保外，不需要核销码验证", TmallConsts.CHANNEL_NAME);
            return;
        }

        // 版本上线前的订单无需核销码校验
        if (orderWork.getReceiveTime().getTime() < DateUtil.parse("2021-07-26 00:00:00").getTime()) {
            log.info("【{}】订单录入时间为版本更新前，不需要核销码验证", TmallConsts.CHANNEL_NAME);
            return;
        }

        // 判断核销码是否存在
        String codeComplete = this.getCompleteCode(orderId);
        if (StringUtil.isNotBlank(codeComplete)) {
            throw new OmsBaseException("已校验核销码，无需要再次进行");
        }

        String outerId = orderWork.getOuterId();
        if (StringUtil.isBlank(outerId)) {
            throw new OmsBaseException("渠道订单id为空");
        }

        // 生成请求数据，进行核销验证
        TmallJSTOrderIdentifyDTO orderIdentifyDTO = new TmallJSTOrderIdentifyDTO();

        orderIdentifyDTO.setTmallOrderId(Long.valueOf(outerId));
        orderIdentifyDTO.setVCode(vCode);

        // 发送数据
        log.info("【{}】同步 工单核销 消息，【{}】", TmallConsts.CHANNEL_NAME, JSON.toJSONString(orderIdentifyDTO));
        ResultDTO resultDTO = this.postTmallJstRequest(TmallConsts.JSZ_ORDER_IDENTIYF_PATH, orderIdentifyDTO);

        String orderLog;
        boolean success = true;
        if (Objects.isNull(resultDTO) || !resultDTO.isStatusBool()) {

            log.info("【{}】同步 工单核销 消息，渠道返回失败，【{}】【{}】", TmallConsts.CHANNEL_NAME,
                    Optional.ofNullable(resultDTO).map(res->res.getMessage()).orElse(""));

            orderLog = String.format("核销码校验失败，核销码:%s", vCode);

            success = false;

        } else {

            // 保存到redis
            setCompleteCode(orderId, vCode);
            orderLog = String.format("核销码校验成功，核销码:%s", vCode);
        }

        // 添加日志
        this.addLog(orderId, outerId, orderLog);

        if (!success) {
            throw new OmsBaseException("工单核销失败，请检查并重试");
        }
    }

    /**
     * 完成验证
     *
     * @param orderId
     * @param workId
     */
    @Override
    public boolean verifyComplete(Long orderId, Long workId) {

        if (NumberUtil.isNullOrZero(orderId) || NumberUtil.isNullOrZero(workId)) {
            return false;
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (Objects.isNull(orderWork)) {
            return false;
        }

        if (!Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_TMALL_QINGE_BW)) {
            return true;
        }

        // 版本上线前的订单无需核销码校验
        if (orderWork.getReceiveTime().getTime() < DateUtil.parse("2021-07-19 00:00:00").getTime()) {
            return true;
        }

        // 人工录单等订单不进行验证
        if (!Objects.equals(orderWork.getInputType(),OrderConsts.ORDER_INPUT_TYPE_API)) {
            return true;
        }

        String vCode = getCompleteCode(orderId);

        return StringUtil.isBlank(vCode) ? false : true;
    }

    /**
     * 读取已校验的核销码
     * @param orderId
     * @return
     */
    @Override
    public String getVerificationCode(Long orderId) throws OmsBaseException {

        if (NumberUtil.isNullOrZero(orderId)) {
            throw new OmsBaseException("订单id不能为空");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("没有对应的订单");
        }

        if (!Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_TMALL_QINGE_BW)) {
            throw new OmsBaseException("订单渠道不为天猫勤鸽保外");
        }

        return getCompleteCode(orderId);
    }

    /**
     * 根据预约时间设置天猫勤鸽渠道的预约时间段
     * @param request
     * @param dutyTime
     */
    private void setTmallReserveTimeSegment(TmallJSTOrderReserveDTO request, Date dutyTime) {

        // 映射关系，10点前 8 - 10，12点前 10 - 12，14点前 12 - 14 ，16点前 14 -16，18点前 16 - 18，后面 第二天 8 - 10

        Calendar calendar = Calendar.getInstance();
        Calendar calendarStart = Calendar.getInstance();
        Calendar calendarEnd = Calendar.getInstance();

        calendar.setTime(dutyTime);
        calendarStart.setTime(dutyTime);
        calendarEnd.setTime(dutyTime);

        calendarStart.set(Calendar.HOUR_OF_DAY, 0);
        calendarStart.set(Calendar.MINUTE, 0);
        calendarStart.set(Calendar.SECOND, 0);
        calendarStart.set(Calendar.MILLISECOND, 0);

        calendarEnd.set(Calendar.HOUR_OF_DAY, 0);
        calendarEnd.set(Calendar.MINUTE, 0);
        calendarEnd.set(Calendar.SECOND, 0);
        calendarEnd.set(Calendar.MILLISECOND, 0);

        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        if ( hour < 10) {
            calendarStart.set(Calendar.HOUR_OF_DAY,8);
            calendarEnd.set(Calendar.HOUR_OF_DAY, 10);
        } else if (hour < 12) {
            calendarStart.set(Calendar.HOUR_OF_DAY,10);
            calendarEnd.set(Calendar.HOUR_OF_DAY, 12);
        } else if (hour < 14) {
            calendarStart.set(Calendar.HOUR_OF_DAY,12);
            calendarEnd.set(Calendar.HOUR_OF_DAY, 14);
        } else if (hour < 16) {
            calendarStart.set(Calendar.HOUR_OF_DAY,14);
            calendarEnd.set(Calendar.HOUR_OF_DAY, 16);
        } else if (hour < 19){
            calendarStart.set(Calendar.HOUR_OF_DAY,16);
            calendarEnd.set(Calendar.HOUR_OF_DAY, 19);
        } else {
            calendarStart.add(Calendar.DAY_OF_MONTH,1);
            calendarEnd.add(Calendar.DAY_OF_MONTH,1);
            calendarStart.set(Calendar.HOUR_OF_DAY,8);
            calendarEnd.set(Calendar.HOUR_OF_DAY, 10);
        }

        Calendar curCalendar = Calendar.getInstance();
        if (calendarStart.getTime().getTime() <= curCalendar.getTime().getTime()) {
            calendarStart.set(Calendar.HOUR_OF_DAY,curCalendar.get(Calendar.HOUR_OF_DAY) + 1);
        }
        
        if (calendarEnd.getTime().getTime() < calendarStart.getTime().getTime()) {
            calendarStart.set(Calendar.HOUR_OF_DAY,calendarStart.get(Calendar.HOUR_OF_DAY) + 1);
        }

        request.setReserveStartTime(calendarStart.getTime().getTime());
        request.setReserveEndTime(calendarEnd.getTime().getTime());
    }

    /**
     * 读取保存的完成核销码
     * @param orderId
     * @return
     */
    private String getCompleteCode(Long orderId) {

        // 参数判断
        if (NumberUtil.isNullOrZero(orderId)) {
            return null;
        }

        // 查询订单扩展数据
        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderId);
        if (Objects.isNull(orderExtend)) {
            return null;
        }

        String outerData = orderExtend.getOuterData();
        if (StringUtil.isBlank(outerData)) {
            return null;
        }

        try {
            TmallOrderExtendDTO tmallOrderExtendDTO = JSON.parseObject(outerData,TmallOrderExtendDTO.class);
            if (Objects.nonNull(tmallOrderExtendDTO)) {
                return tmallOrderExtendDTO.getIdentifyCode();
            }
        } catch (Exception e) {
            log.info("【{}】 解析天猫勤鸽渠道订单扩展数据异常 【{}】", TmallConsts.CHANNEL_NAME, outerData);
        }

        return null;
    }

    /**
     * 保存完成核销码
     * @param orderId
     * @param completeCode
     */
    private void setCompleteCode(Long orderId, String completeCode) {
        // 参数判断
        if (NumberUtil.isNullOrZero(orderId)) {
            return;
        }

        // 查询订单扩展数据
        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(orderId);
        if (Objects.isNull(orderExtend)) {
            return;
        }

        TmallOrderExtendDTO tmallOrderExtendDTO = null;
        String outerData = orderExtend.getOuterData();

        if (StringUtil.isNotBlank(outerData)) {
            // 解析数据
            try {
                tmallOrderExtendDTO = JSON.parseObject(outerData, TmallOrderExtendDTO.class);
            } catch (Exception e) {
                log.info("【{}】 解析天猫勤鸽渠道订单扩展数据异常 【{}】", TmallConsts.CHANNEL_NAME, outerData);
            }
        }

        // 保存核销码
        if (Objects.isNull(tmallOrderExtendDTO)) {
            tmallOrderExtendDTO = new TmallOrderExtendDTO();
        }

        tmallOrderExtendDTO.setIdentifyCode(completeCode);
        orderExtend.setOuterData(JSON.toJSONString(tmallOrderExtendDTO));
        orderExtendService.updateOrderExtend(orderExtend);
    }

    /**
     * 根据天猫工单创建订单
     * @param tmallOrderData
     * @throws OmsBaseException
     */
    @Override
    public Long createOrder(TmallOrderCreateData tmallOrderData) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(tmallOrderData)) {
            throw new OmsBaseException("工单参数为空");
        }

        String outerId = NumberUtil.isNullOrZero(tmallOrderData.getOrderId()) ? "" : String.valueOf(tmallOrderData.getOrderId());

        // 订单去重，并保存渠道订单处理状态
        this.saveTmallOrderStatus(outerId, TmallConsts.TMALL_ORDER_STATE_CREATING);

        // 创建订单
        OrderWork orderWork;
        try {
            // 生成创建订单的数据
            CreateOrderDTO createOrderDTO = buildCreateOrderDTO(tmallOrderData);
            OrderBO orderBO = proxyOrderBService.createOrder(createOrderDTO);
            orderWork = orderBO.getOrderWork();

        } catch (OmsBaseException omsBaseException) {

            log.info("【{}】保存订单异常，OmsBaseException【{}】 ", TmallConsts.CHANNEL_NAME,omsBaseException.getMessage());
            this.saveTmallOrderStatus(outerId, TmallConsts.TMALL_ORDER_STATE_CREATE_FAILED);
            throw omsBaseException;

        } catch (Exception exception) {

            log.info("【{}】保存订单失败，Exception【{}】 ", TmallConsts.CHANNEL_NAME,exception.getMessage());
            this.saveTmallOrderStatus(outerId, TmallConsts.TMALL_ORDER_STATE_CREATE_FAILED);
            throw new OmsBaseException("创建订单失败");
        }

        log.info("【{}】保存订单成功 OrderId:[{}]", TmallConsts.CHANNEL_NAME, orderWork.getOrderId());
        this.saveTmallOrderStatus(outerId, TmallConsts.TMALL_ORDER_STATE_CREATE_SUCCESS);

        // 工单自动流转
        workFlowContextBService.asyncAutoFlow(orderWork.getOrderId(),orderWork.getWorkId());

        return orderWork.getOrderId();
    }

    /**
     * 订单改约（渠道方）
     * @param tmallOrderReserveData
     * @throws OmsBaseException
     */
    @Override
    public void changeOrderDutytime(TmallOrderReserveData tmallOrderReserveData) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(tmallOrderReserveData) || NumberUtil.isNullOrZero(tmallOrderReserveData.getOrderId())) {
            throw new OmsBaseException("参数为空");
        }

        String outerId = String.valueOf(tmallOrderReserveData.getOrderId());
        // 工单判断
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(outerId, OrderConsts.CHANNEL_ID_TMALL_QINGE_BW);
        if (Objects.isNull(zsOrderWorkVO)) {
            throw new OmsBaseException("工单不存在");
        }

        // 计算预约时间，优先设置为开始时间
        Date dutyTime = getDutytimeByTmallReserveTime(tmallOrderReserveData);
        if (Objects.isNull(dutyTime)) {
            throw new OmsBaseException("预约时间为空");
        }

        log.info("【{}】用户修改工单预约时间，【{}】【{}】", TmallConsts.CHANNEL_NAME, zsOrderWorkVO.getOrderId(), JSON.toJSONString(tmallOrderReserveData));

        UpdateOrderDTO updateOrderDTO = new UpdateOrderDTO();
        updateOrderDTO.setOrderId(zsOrderWorkVO.getOrderId());
        updateOrderDTO.setWorkId(zsOrderWorkVO.getWorkId());
        updateOrderDTO.setDutyTime(dutyTime);

        try {
            proxyOrderBService.updateOrder(updateOrderDTO);
        } catch (OmsBaseException omsBaseException) {
            log.error("【{}】更新订单预约时间失败 消息:[{}]", TmallConsts.CHANNEL_NAME, omsBaseException.getMessage());
            throw new OmsBaseException("改约失败");
        }

        // 记录日志
        String orderLog = String.format("用户修改预约时间，开始时间：%s，结束时间：%s, 期望时间：%s，改约时间：%s",
                DateUtil.toString(tmallOrderReserveData.getReserveStartTime()),
                DateUtil.toString(tmallOrderReserveData.getReserveEndTime()),
                DateUtil.toString(tmallOrderReserveData.getUserExpectDate()),
                DateUtil.toString(dutyTime));

        this.addLog(zsOrderWorkVO.getOrderId(), outerId, orderLog);
    }

    /**
     * 订单取消（渠道方）
     * @param tmallOrderDataBase
     * @throws OmsBaseException
     */
    @Override
    public void cancelOrder(TmallOrderDataBase tmallOrderDataBase) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(tmallOrderDataBase) || NumberUtil.isNullOrZero(tmallOrderDataBase.getOrderId())) {
            throw new OmsBaseException("参数为空");
        }

        String outerId = String.valueOf(tmallOrderDataBase.getOrderId());
        // 工单判断
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(outerId, OrderConsts.CHANNEL_ID_TMALL_QINGE_BW);
        if (Objects.isNull(zsOrderWorkVO)) {
            throw new OmsBaseException("工单不存在");
        }

        log.info("【{}】取消订单，【{}】【{}】", TmallConsts.CHANNEL_NAME, zsOrderWorkVO.getOrderId(), outerId);

        // 取消订单
        CancelOrderDTO cancelOrderDTO = new CancelOrderDTO();
        cancelOrderDTO.setOrderId(zsOrderWorkVO.getOrderId());
        cancelOrderDTO.setOuterId(outerId);
        cancelOrderDTO.setChannelId(zsOrderWorkVO.getChannelId());
        cancelOrderDTO.setOperatorId((long) zsOrderWorkVO.getChannelId());
        cancelOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        cancelOrderDTO.setRemark("渠道取消");

        try {
            proxyOrderBService.cancelOrder(cancelOrderDTO);
        } catch (OmsBaseException omsBaseException) {
            log.error("【{}】取消订单失败 消息:[{}]", TmallConsts.CHANNEL_NAME, omsBaseException.getMessage());

            throw new OmsBaseException("取消订单失败");
        }
    }

    /**
     * 订单核销完成（渠道方）
     * @param tmallOrderDataBase
     * @throws OmsBaseException
     */
    @Override
    public void completeOrder(TmallOrderDataBase tmallOrderDataBase) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(tmallOrderDataBase) || NumberUtil.isNullOrZero(tmallOrderDataBase.getOrderId())) {
            throw new OmsBaseException("参数为空");
        }

        String outerId = String.valueOf(tmallOrderDataBase.getOrderId());
        // 工单判断
        ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(outerId, OrderConsts.CHANNEL_ID_TMALL_QINGE_BW);
        if (Objects.isNull(zsOrderWorkVO)) {
            throw new OmsBaseException("工单不存在");
        }

        log.info("【{}】用户进行核销操作，【{}】【{}】", TmallConsts.CHANNEL_NAME, zsOrderWorkVO.getOrderId(), outerId);

        // 保存到核销完成提示
        setCompleteCode(zsOrderWorkVO.getOrderId(), "客户已核销，无需再次核销");

        // 记录日志
        String orderLog = "渠道核销成功";
        this.addLog(zsOrderWorkVO.getOrderId(), outerId, orderLog);
    }

    /**
     * 生成订单创建信息
     * @return CreateOrderDTO
     */
    private CreateOrderDTO buildCreateOrderDTO(TmallOrderCreateData tmallOrderData) {

        // 订单创建数据
        CreateOrderDTO createOrderDTO = new CreateOrderDTO();

        // 输入类型
        createOrderDTO.setInputType(OrderConsts.ORDER_INPUT_TYPE_API);

        // 渠道id
        createOrderDTO.setChannelId(OrderConsts.CHANNEL_ID_TMALL_QINGE_BW);

        // 外部订单id
        createOrderDTO.setOuterId(String.valueOf(tmallOrderData.getOrderId()));

        // 主订单号 -> 渠道扩展订单号
        if (NumberUtil.isNotNullOrZero(tmallOrderData.getParentBizOrderId())) {
            createOrderDTO.setExtOuterId(String.valueOf(tmallOrderData.getParentBizOrderId()));
        }

        // 服务订单号 -> 渠道扩展子订单号
        if (NumberUtil.isNotNullOrZero(tmallOrderData.getServiceOrderId())) {
            createOrderDTO.setExtOuterSubId(String.valueOf(tmallOrderData.getServiceOrderId()));
        }

        // 联系人
        createOrderDTO.setContactName(tmallOrderData.getUserName());

        // 联系人电话
        createOrderDTO.setTelephone(tmallOrderData.getUserPhone());

        // 性别
        createOrderDTO.setGender(GlobalDict.GENDER_NO);

        // 预约时间 优先设置为开始时间
        Date dutyTime = tmallOrderData.getBuyerExpectDate();
        if (Objects.isNull(dutyTime)) {
            dutyTime = Optional.ofNullable(tmallOrderData.getReserveStartTime()).orElse(tmallOrderData.getReserveEndTime());
        }

        if (Objects.nonNull(dutyTime)) {
            createOrderDTO.setDutyTime(dutyTime);
        }

        // 地址
        String address = tmallOrderData.getUserAddress();
        createOrderDTO.setAddress(address);

        // 厂商单
        createOrderDTO.setFactory(com.zmn.consts.GlobalConsts.NO);

        // 业务类型
        createOrderDTO.setBizType(com.zmn.consts.GlobalConsts.BIZ_TYPE_C);

        // 平台
        createOrderDTO.setPlat(com.zmn.consts.GlobalConsts.PLAT_MARK_YEYX);

        // 禁止弃单
        createOrderDTO.setDisableDiscard(com.zmn.consts.GlobalConsts.NO);

        // 操作人
        createOrderDTO.setOperator("系统");

        // 操作人id
        createOrderDTO.setOperatorId((long) com.zmn.consts.GlobalConsts.OPERATE_USER_TYPE_SYSTEM);

        // 操作者类型
        createOrderDTO.setOperatorType(com.zmn.consts.GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

        // 城市id
        Integer cityId = 500100;
        do {
            // 详细地址获取经纬度
            LngLatLocation areaLocation = baiduMapBService.location(address);
            if (Objects.isNull(areaLocation)) {

                log.info("【{}】地址信息解析失败 -【{}】",TmallConsts.CHANNEL_NAME, address);
                break;
            }

            createOrderDTO.setLatitude(Double.valueOf(areaLocation.getLat()));
            createOrderDTO.setLongitude(Double.valueOf(areaLocation.getLng()));

            // 经纬度查找区域信息
            ResponseDTO<AreaDRO> areaResponse = areaListRemoteService.getAreaByLatAndLng(Double.valueOf(areaLocation.getLng()), Double.valueOf(areaLocation.getLat()));
            if (Objects.isNull(areaResponse) || Objects.isNull(areaResponse.getData())) {
                log.info("【{}】根据经纬度查找地址信息失败",TmallConsts.CHANNEL_NAME);
                break;
            }

            cityId = areaResponse.getData().getParentId();

            // 再设一次经纬度
            Double longitude = Double.valueOf(areaResponse.getData().getLongitude());
            Double latitude = Double.valueOf(areaResponse.getData().getLatitude());
            createOrderDTO.setLongitude(longitude);
            createOrderDTO.setLatitude(latitude);

        } while (false);

        createOrderDTO.setCityId(cityId);

        boolean unknowProduct = false; // 未知产品标识
        {// 产品 和 渠道预付
            // 1. 查找产品
            Integer productId = null;
            int prepayAmount = 0;
            productIdSegment: {
                TmallProductPrepey tmallProductPrepey = null;  // 天猫产品价格描述对象

                // a. 从运营人员配置的渠道产品映射中查询对应的啄木鸟产品
                tmallProductPrepey = Optional.ofNullable(
                        channelProductThirdListRemoteService.listByChannelIdAndProductParentIdAndSubId(
                                OrderConsts.CHANNEL_ID_TMALL_QINGE_BW,
                                String.valueOf(tmallOrderData.getAuctionId()),
                                String.valueOf(tmallOrderData.getSkuId())
                        ))
                        .map(ResponseDTO::getData)
                        .map(list -> list.isEmpty() ? null : list.get(0))
                        .map(productDRO -> TmallPrepayMapper.getPrepayByProductId(productDRO.getProductId()))
                        .orElse(null);
                if (tmallProductPrepey != null) {
                    productId = tmallProductPrepey.getProductId();
                    prepayAmount = tmallProductPrepey.getSellMoney();
                    break productIdSegment;
                }

                // b. 使用天猫的 auctionId 和 skuId 直接查 TmallProductPrepey
                tmallProductPrepey = TmallPrepayMapper.getProductPrepeyByTmallGoods(
                        String.valueOf(tmallOrderData.getAuctionId()),
                        String.valueOf(tmallOrderData.getSkuId())
                );
                if (tmallProductPrepey != null) {
                    productId = tmallProductPrepey.getProductId();
                    prepayAmount = tmallProductPrepey.getSellMoney();
                    break productIdSegment;
                }

                // c. 查不到产品，使用“其他”，预付款为0
                productId = OrderConsts.CHANNEL_DISABLED_PRODUCT_ID;
                unknowProduct = true;
            }

            // 设置产品
            OrderProductDTO orderProductDTO = new OrderProductDTO();
            orderProductDTO.setProductId(productId);
            orderProductDTO.setNumber(Optional.ofNullable(tmallOrderData.getBuyAmount())
                    .map(Long::intValue)
                    .filter(num -> num > 0)
                    .orElse(1)
            );
            createOrderDTO.setOrderProductList(Arrays.asList(orderProductDTO));

            // 设置渠道预付款
            if (prepayAmount > 0) {
                int totalPrepayAmount = prepayAmount * orderProductDTO.getNumber();
                createOrderDTO.setChannelPrepayAmount(totalPrepayAmount * 100); // 单位：分
                createOrderDTO.setChannelPrepayStatus(PayConsts.PAY_STATUS_DONE);
            }
        }

        // 日志记录
        StringBuilder sbOperateLog = new StringBuilder();
        sbOperateLog.append("<br/> 用户名称：").append(tmallOrderData.getUserName()).
                append("<br/> 用户联系电话：").append(tmallOrderData.getUserPhone()).
                append("<br/> 用户地址：").append(address).
                append("<br/> 服务订单id：").append(tmallOrderData.getServiceOrderId()).
                append("<br/> 服务商id：").append(tmallOrderData.getServiceTpId()).
                append("<br/> 服务商品id：").append(tmallOrderData.getAuctionId()).
                append("<br/> 服务商品标题：").append(tmallOrderData.getAuctionTitle()).
                append("<br/> 服务商品类目：").append(tmallOrderData.getCategoryId()).
                append("<br/> 服务商品商家编码：").append(tmallOrderData.getOuterIdSku()).
                append("<br/> 服务商品SkuId：").append(tmallOrderData.getSkuId()).
                append("<br/> 服务商品Sku描述：").append(tmallOrderData.getSkuDesc()).
                append("<br/> 工单状态编码：").append(tmallOrderData.getStatusCode()).
                append("<br/> 主订单号：").append(tmallOrderData.getParentBizOrderId()).
                append("<br/> 服务履约类型：").append(tmallOrderData.getFulfilTypeCode()).
                append("<br/> 创建时间：").append(DateUtil.toString(tmallOrderData.getCreateTime())).
                append("<br/> 服务类型：").append(tmallOrderData.getServiceCode()).
                append("<br/> 业务类型：").append(tmallOrderData.getBizCode()).
                append("<br/>");

        if (unknowProduct) {
            sbOperateLog.append("未识别出产品信息，未设置预付款");
        }

        createOrderDTO.setOperatorLogRemark(sbOperateLog.toString());

        // 渠道订单扩展数据
        TmallOrderExtendDTO tmallOrderExtendDTO = new TmallOrderExtendDTO();
        tmallOrderExtendDTO.setAuctionId(tmallOrderData.getAuctionId());
        tmallOrderExtendDTO.setCategoryId(tmallOrderData.getCategoryId());
        tmallOrderExtendDTO.setSkuId(tmallOrderData.getSkuId());
        tmallOrderExtendDTO.setSkuDesc(tmallOrderData.getSkuDesc());
        tmallOrderExtendDTO.setParentBizOrderId(tmallOrderData.getParentBizOrderId());
        tmallOrderExtendDTO.setStatusCode(tmallOrderData.getStatusCode());
        tmallOrderExtendDTO.setFulfilTypeCode(tmallOrderData.getFulfilTypeCode());
        tmallOrderExtendDTO.setBizCode(tmallOrderData.getBizCode());
        tmallOrderExtendDTO.setServiceCode(tmallOrderData.getServiceCode());
        tmallOrderExtendDTO.setCreateTime(tmallOrderData.getCreateTime());

        createOrderDTO.setOuterData(JSON.toJSONString(tmallOrderExtendDTO));
        return createOrderDTO;
    }

    /**
     *
     * @param tmallOrderStatus
     * @throws OmsBaseException
     */
    private void queryTmallOrderData(TmallOrderStatus tmallOrderStatus) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(tmallOrderStatus)) {
            throw new OmsBaseException("查询参数为空");
        }

        // 保存处理状态
        this.saveTmallOrderStatus(String.valueOf(tmallOrderStatus.getOrderId()),TmallConsts.TMALL_ORDER_STATE_QUERYING);

        // 向聚石塔服务发送查询请求
        TmallOrderCreateData tmallOrderData;
        try {

            tmallOrderData = this.postJstQueryOrderRequest(tmallOrderStatus.getOrderId());
        } catch (OmsBaseException e) {

            this.saveTmallOrderStatus(String.valueOf(tmallOrderStatus.getOrderId()),TmallConsts.TMALL_ORDER_STATE_QUERY_FAILED);
            throw e;
        }

        // 创建订单
        this.createOrder(tmallOrderData);
    }

    /**
     * 读取redis中的渠道订单状态
     * @param outerId
     * @return
     */
    private TmallOrderStatus getTmallOrderStatus(String outerId) {

        if (StringUtil.isBlank(outerId)) {
            return null;
        }

        String redisKey = String.format(RedisKeyConsts.TMALL_QINGE_ORDER_STATUS_REDIS_KEY, outerId);
        String redisValue = redisManager.get(redisKey);

        if (StringUtil.isBlank(redisValue)) {
            return null;
        }

        try {
            return JSON.parseObject(redisValue, TmallOrderStatus.class);
        } catch(Exception e) {
            log.info("【{}】读取天猫勤鸽订单缓存异常【{}】", TmallConsts.CHANNEL_NAME, e.getMessage());
        }

        return null;
    }

    /**
     * 保存渠道订单状态到redis
     * @param outerId
     * @param status
     */
    private void saveTmallOrderStatus(String outerId, Integer status) throws OmsBaseException {

        if (StringUtil.isBlank(outerId)) {
            throw new OmsBaseException("渠道订单id不能为空");
        }

        // 订单查询，订单创建 判断订单是否已经存在
        if (Objects.equals(status, TmallConsts.TMALL_ORDER_STATE_QUERYING) ||
                Objects.equals(status, TmallConsts.TMALL_ORDER_STATE_CREATING)) {

            // 工单判断
            ZsOrderWorkVO zsOrderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(outerId, OrderConsts.CHANNEL_ID_TMALL_QINGE_BW);
            if (!Objects.isNull(zsOrderWorkVO)) {
                throw new OmsBaseException("工单已经创建");
            }
        }

        // 添加到列表
        Boolean existInList = redisManager.sexists(RedisKeyConsts.TMALL_QINGE_ORDER_LIST_REDIS_KEY,outerId);
        if (Objects.equals(status, TmallConsts.TMALL_ORDER_STATE_QUERYING) && !existInList) {
            redisManager.sset(RedisKeyConsts.TMALL_QINGE_ORDER_LIST_REDIS_KEY,outerId);
        }

        String redisKey = String.format(RedisKeyConsts.TMALL_QINGE_ORDER_STATUS_REDIS_KEY, outerId);
        TmallOrderStatus orderStatus = new TmallOrderStatus(Long.valueOf(outerId), status);
        TmallOrderStatus oldOrderStatus = getTmallOrderStatus(outerId);

        // 判断是否有数据保存
        if (Objects.isNull(oldOrderStatus)) {
            redisManager.setex(redisKey, JSON.toJSONString(orderStatus),TmallConsts.REDIS_EXPIRE_SECONDS);
            return;
        }

        Integer oldStatus = Optional.ofNullable(oldOrderStatus.getStatus()).orElse(0);
        Integer queryCount = Optional.ofNullable(oldOrderStatus.getQueryCount()).orElse(0);

        switch (status) {
            case TmallConsts.TMALL_ORDER_STATE_QUERYING:

                if (Objects.equals(oldStatus, TmallConsts.TMALL_ORDER_STATE_QUERYING) ||
                        Objects.equals(oldStatus, TmallConsts.TMALL_ORDER_STATE_CREATING) ||
                        Objects.equals(oldStatus, TmallConsts.TMALL_ORDER_STATE_CREATE_SUCCESS)) {
                    throw new OmsBaseException("工单正在查询/创建/已经创建");
                }

                if (queryCount >= TmallConsts.TMALL_ORDER_MAX_QUERY_COUNT) {
                    throw new OmsBaseException("查询已经超出最大次数");
                }

                queryCount++;
                break;

            case TmallConsts.TMALL_ORDER_STATE_CREATING:
                if (Objects.equals(oldStatus, TmallConsts.TMALL_ORDER_STATE_CREATING) ||
                        Objects.equals(oldStatus, TmallConsts.TMALL_ORDER_STATE_CREATE_SUCCESS)) {
                    throw new OmsBaseException("订单正在创建中或已经创建");
                }
        }

        orderStatus.setQueryCount(queryCount);
        redisManager.set(redisKey, JSON.toJSONString(orderStatus));

        if (Objects.equals(status, TmallConsts.TMALL_ORDER_STATE_CREATE_SUCCESS) && existInList) {
            redisManager.sdel(RedisKeyConsts.TMALL_QINGE_ORDER_LIST_REDIS_KEY, outerId);
        }
    }

    /**
     * 发送天猫勤鸽渠道订单查询请求
     * @param orderId
     * @return
     * @throws OmsBaseException
     */
    public TmallOrderCreateData postJstQueryOrderRequest(Long orderId) throws OmsBaseException{

        // 参数判断
        if (NumberUtil.isNullOrZero(orderId)) {
            throw new OmsBaseException("查询的渠道订单id不能为空");
        }

        // 生成请求的参数
        String postUrl = TmallConsts.JST_URL + TmallConsts.JSZ_QUERY_ORDER_PATH;
        Map<String,String> params = new HashMap<>(1);
        params.put("orderId",String.valueOf(orderId));

        log.info("【{}】发送请求，URL【{}】,参数【{}】",TmallConsts.CHANNEL_NAME,postUrl,params.toString());

        try {

            String response;
            if (postUrl.matches("https(.*)")) {
                response = HttpUtil.httpsPost(postUrl, params);
            } else {
                response = HttpUtil.httpPost(postUrl, params);
            }

            log.info("【{}】发送请求应答【{}】",TmallConsts.CHANNEL_NAME,response);

            if (StringUtil.isBlank(response)) {
                throw new OmsBaseException("发送查询请求，应答数据不正确");
            }

            ResultDTO<TmallOrderCreateData> resultDTO = JSON.parseObject(response,ResultDTO.class);
            if (Objects.isNull(resultDTO)) {
                throw new OmsBaseException("发送查询请求，应答数据解析失败");
            }

            if (!resultDTO.isStatusBool()) {
                throw new OmsBaseException(String.format("发送查询请求，返回失败,%s", resultDTO.getMessage()));
            }

            return resultDTO.getData();
        } catch (Exception exception) {
            throw new OmsBaseException(String.format("发送请求失败,%s",Objects.nonNull(exception)? exception.getMessage():"网络请求异常"));
        }
    }

    /**
     * 发送天猫勤鸽渠道订单查询请求
     * @param path
     * @return
     * @throws OmsBaseException
     */
    protected ResultDTO postTmallJstRequest(String path, TmallJSTRequestDTO requestDTO) throws OmsBaseException{

        // 参数判断
        if (Objects.isNull(requestDTO)) {
            throw new OmsBaseException("参数不能为空");
        }

        // 生成请求的参数
        String postUrl = TmallConsts.JST_URL + path;
        Map<String,String> params = objectToMap(requestDTO);

        log.info("【{}】发送请求，URL【{}】,参数【{}】",TmallConsts.CHANNEL_NAME,postUrl,params.toString());

        try {

            String response;
            if (postUrl.matches("https(.*)")) {
                response = HttpUtil.httpsPost(postUrl, params);
            } else {
                response = HttpUtil.httpPost(postUrl, params);
            }

            log.info("【{}】发送请求应答【{}】",TmallConsts.CHANNEL_NAME,response);

            if (StringUtil.isBlank(response)) {
                throw new OmsBaseException("发送查询请求，应答数据不正确");
            }

            ResultDTO resultDTO = JSON.parseObject(response,ResultDTO.class);
            if (Objects.isNull(resultDTO)) {
                throw new OmsBaseException("发送查询请求，应答数据解析失败");
            }

            if (!resultDTO.isStatusBool()) {
                log.info("【{}】发送请求返回失败【{}】",TmallConsts.CHANNEL_NAME,resultDTO.getMessage());
            }

            return resultDTO;
        } catch (Exception exception) {
            throw new OmsBaseException(String.format("发送请求失败,%s",Objects.nonNull(exception)? exception.getMessage():"网络请求异常"));
        }
    }

    /**
     * 添加订单日志
     * @param orderId
     * @param outerId
     * @param orderLog
     */
    private void addLog(Long orderId, String outerId, String orderLog) {

        if (NumberUtil.isNullOrZero(orderId) || StringUtil.isBlank(outerId) || StringUtil.isBlank(orderLog)) {
            return;
        }

        OrderLogDTO orderLogDTO = new OrderLogDTO();
        orderLogDTO.setOrderId(orderId);
        orderLogDTO.setOuterId(outerId);
        orderLogDTO.setChannelId(OrderConsts.CHANNEL_ID_TMALL_QINGE_BW);
        orderLogDTO.setOperatorId((long) OrderConsts.CHANNEL_ID_TMALL_QINGE_BW);
        orderLogDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
        orderLogDTO.setType(OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_REMARK);
        orderLogDTO.setOperatorLogRemark(orderLog);

        try {
            proxyOrderBService.addOrderLog(orderLogDTO);
        } catch (OmsBaseException e) {
            log.info("【{}】 添加订单日志异常，【{}】【{}】【{}】", TmallConsts.CHANNEL_NAME, orderId, outerId, orderLog);
        }
    }

    /**
     * 将对象实体转换为map，按照名称排序
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, String> objectToMap (Object obj){

        // 参数判断
        if (Objects.isNull(obj)) {
            return null;
        }

        Class<?> objClass = obj.getClass();
        TreeMap<String,String> map = Maps.newTreeMap();

        // 循环获取类和父类的字段，并取值
        while (objClass!=null && !("java.lang.object").equals(objClass.getName().toLowerCase())) {

            Field[] fields = objClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String name = field.getName();
                Object value = null;
                try {
                    value = field.get(obj);
                } catch (IllegalAccessException exception) {
                    log.info("#TmallServiceImpl#objectToMap# catch IllegalAccessException");
                }

                if (Objects.nonNull(value)) {
                    map.put(name, value.toString());
                }
            }

            objClass = objClass.getSuperclass();
        }

        return map;
    }

    /**
     * 预约时间转换
     *
     * @param reserveData
     * @return
     */
    protected Date getDutytimeByTmallReserveTime(TmallOrderReserveData reserveData) {

        if (Objects.isNull(reserveData)) {
            return null;
        }

        Date dutyTime = reserveData.getUserExpectDate();
        if (Objects.nonNull(dutyTime)) {
            return dutyTime;
        }

        dutyTime = reserveData.getReserveStartTime();
        if (Objects.nonNull(dutyTime)) {
            return dutyTime;
        }

        return reserveData.getReserveEndTime();
    }
     /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        
    }

}
